import tokenMgr from '../cookieMgr/tokenMgr';

interface Sending {
  controller: AbortController | null;
  requestId: number;
}

const sendings: Map<string, Sending> = new Map();

const request = async (url: string, options: RequestInit = {}) => {
  try {
    const path = url.split('?')[0].toLowerCase(); // 当前请求的接口地址
    const existingSending = sendings.get(path); // 查找请求
    // 如果不是第一次请求
    if (existingSending) {
      // 上次请求未完成，清除
      if (existingSending.controller) {
        existingSending.controller.abort();
        existingSending.controller = null;
      }
    }
    // 第一次请求
    else {
      // 添加到请求集合
      sendings.set(path, { controller: null, requestId: 0 });
    }
    const sending = sendings.get(path)!;
    const controller = new AbortController();
    options.signal = controller.signal;
    sending.controller = controller;
    const currentId = ++sending.requestId;
    try {
      const res = await fetch(url, options);
      sending.controller = null;
      if (currentId != sending.requestId) {
        throw new Error('该请求已过期');
      }
      // 处理异常状态码
      if (res.status >= 400) {
        switch (res.status) {
          case 401:
            location.href = '/login';
            break;
        }
      }
      console.log(sendings);
      return res.json();
    } catch (e) {
      sending.controller = null;
      throw e;
    }
  } catch (error) {
    // 统一处理网络错误或业务错误
    console.error('请求异常:', error);
    return error;
    // throw new Error(error.message || "网络请求失败"); // 抛出错误供调用方处理
  }
};

const instance = {
  get: (url: string, params = {} as any, options: RequestInit = {}) => {
    for (let key in params) {
      if (params[key] == null) {
        delete params[key];
      }
    }
    // 从本地存储获取token，根据实际情况修改获取方式
    const token = tokenMgr.getToken();

    // 合并请求头，自动携带token
    const headers = {
      'Content-Type': 'application/json',
      ...options.headers,
      Authorization: `Bearer ${token}`,
    };
    return request(
      buildGetUrl(
        import.meta.env.VITE_APP_API_URL + (url.startsWith('/') ? url : '/' + url),
        params
      ),
      {
        ...{ headers, ...options },
        method: 'get',
      }
    );
  },
  post: (url: string, data = {} as any, options: RequestInit = {}) => {
    for (let key in data) {
      if (data[key] == null) {
        delete data[key];
      }
    }
    // 从本地存储获取token，根据实际情况修改获取方式
    const token = tokenMgr.getToken();

    // 合并请求头，自动携带token
    const headers = {
      'Content-Type': 'application/json',
      ...options.headers,
      Authorization: `Bearer ${token}`,
    };
    return request(import.meta.env.VITE_APP_API_URL + (url.startsWith('/') ? url : '/' + url), {
      body: JSON.stringify(data),
      ...{ headers, ...options },
      method: 'post',
    });
  },
  upload: (url: string, formData = new FormData(), options: RequestInit = {}) => {
    const token = tokenMgr.getToken();
    // 合并请求头，自动携带token
    const headers = {
      ...options.headers,
      Authorization: `Bearer ${token}`,
    };
    return request(import.meta.env.VITE_APP_API_URL + (url.startsWith('/') ? url : '/' + url), {
      body: formData,
      ...{ ...options, headers: headers },
      method: 'post',
    });
  },
};

/**
 * 将对象转换为URL查询字符串
 * @param {Object} params - 要转换的参数对象
 * @param {string} [prefix] - 可选前缀（用于递归处理嵌套对象）
 * @returns {string} 查询字符串（不带问号）
 */
function serializeParams(params: any, prefix = ''): string {
  const query = [];

  for (const [key, value] of Object.entries(params)) {
    if (value === null || value === undefined) {
      continue; // 跳过null和undefined
    }

    const encodedKey = prefix ? `${prefix}[${encodeURIComponent(key)}]` : encodeURIComponent(key);

    if (Array.isArray(value)) {
      // 处理数组
      value.forEach((item, i) => {
        if (item !== null && item !== undefined) {
          query.push(`${encodedKey}=${encodeURIComponent(item)}`);
        }
      });
    } else if (typeof value === 'object' && !(value instanceof Date)) {
      // 递归处理嵌套对象（排除Date对象）
      query.push(serializeParams(value, encodedKey));
    } else {
      // 处理基本类型和Date
      const val =
        value instanceof Date ? value.toISOString() : (value as string | number | boolean);
      query.push(`${encodedKey}=${encodeURIComponent(val)}`);
    }
  }

  return query.join('&');
}

/**
 * 将参数对象转换为完整的GET请求URL
 * @param {string} baseUrl - 基础URL
 * @param {Object} params - 参数对象
 * @returns {string} 完整的URL
 */
function buildGetUrl(baseUrl: string, params = {}) {
  const queryString = serializeParams(params);
  const separator = baseUrl.includes('?') ? '&' : '?';
  return queryString ? `${baseUrl}${separator}${queryString}` : baseUrl;
}

export { request, instance };
